From 0d6f3d721b166094af7f186914d73237eb523793 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 29 Sep 2006 09:14:28 +0100 Subject: [PATCH] [XENBUS] Don't perform normal state-machine transitions and notifications during shutdown. When rootfs goes away this can cause the system to hang, as we notify userspace etc. Instead we forcibly reset the state machine back to state Closed if we are a frontend driver, to get the backend to release resources. Necessary if we are going to kexec. Signed-off-by: Keir Fraser --- .../drivers/xen/blkfront/blkfront.c | 2 +- .../drivers/xen/xenbus/xenbus_probe.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c index 4c44d7608d..83630ee2ec 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c @@ -273,7 +273,7 @@ static void backend_changed(struct xenbus_device *dev, xenbus_dev_fatal(dev, -ENODEV, "bdget failed"); down(&bd->bd_sem); - if (info->users > 0 && system_state == SYSTEM_RUNNING) + if (info->users > 0) xenbus_dev_error(dev, -EBUSY, "Device in use; refusing to close"); else diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c index bcd1f6df06..87c9e6ed90 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c @@ -322,6 +322,20 @@ static void otherend_changed(struct xenbus_watch *watch, DPRINTK("state is %d (%s), %s, %s", state, xenbus_strstate(state), dev->otherend_watch.node, vec[XS_WATCH_PATH]); + /* + * Ignore xenbus transitions during shutdown. This prevents us doing + * work that can fail e.g., when the rootfs is gone. + */ + if (system_state > SYSTEM_RUNNING) { + struct xen_bus_type *bus = bus; + bus = container_of(dev->dev.bus, struct xen_bus_type, bus); + /* If we're frontend, drive the state machine to Closed. */ + /* This should cause the backend to release our resources. */ + if ((bus == &xenbus_frontend) && (state == XenbusStateClosing)) + xenbus_frontend_closed(dev); + return; + } + if (drv->otherend_changed) drv->otherend_changed(dev, state); } -- 2.30.2